#include "main.h"

bool is_operator(char symbol) {
	char operator[7] = {'+','-','*','/','(',')','#'};
	for(int i= 0; i<7; ++i)
	{
		if(operator[i] == symbol)
		{
			return 1;
		}
	}
	return 0;
}

// 判断刚扫描到的symbol是否操作数。如果symbol是操作数，返回1，否则返回0。
bool is_operand(char symbol) {
	char operand[10] = {'0','1','2','3','4','5','6','7','8','9'};
	for(int i= 0; i<10; ++i)
	{
		if(operand[i] == symbol)
		{
			return 1;
		}
	}
	return 0;
}

// 初始化名为s的栈，初始化成功，返回0，否则返回1。
int init_stack(Stack * s) {
	(*s) = malloc(sizeof(struct stack));
	int * p = (int*)malloc(STACK_MAX_SIZE*sizeof(int));
	(*s)->base = p;
	if(!(*s)->base)//分配失败时的处理方式
		return 1;
	(*s)->top = (*s)->base ;
	(*s)->number_of_elements = STACK_MAX_SIZE;
	return 0;
}

// 入栈。返回值表示是否压栈成功：0，成功；1，不成功。
int push(Stack s, char operator_or_operand) {
	if(s->top - s->base >= s->number_of_elements){
		return 1;
	}else {
		*(s->top) = operator_or_operand;
		s->top++;
		return 0;
	}
}

// 出栈。返回值表示是否出栈成功：0，成功，1，不成功
int pop(Stack s, char* p_operator_or_operand) {
	if(s->top == s->base)
		return 1;
	s->top--;
	*p_operator_or_operand= *(s->top);
	return 0;
}

// 只返回栈顶元素，通过result变量返回栈顶元素的值。函数返回值用于表示执行状态：0，成功；1，不成功。
int get_top(Stack s, char * result) {
	if(s->base==s->top){
		return 1;
	}      //栈空
	else{
		*result=*(s->top-1);
		return 0;
	}
}

int compare_operators(char operator_on_stack_top,char just_scanned_operator) {
	int i, j;
	char youxianji[][7] = {
		/*运算符之间的优先级制作成一张表格*/
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', '0'},
{'>', '>', '>', '>', '0', '>', '>'},
{'<', '<', '<', '<', '<', '0', '='}
	};
	switch(operator_on_stack_top){
		case '+': i=0; break;
		case '-': i=1; break;
		case '*': i=2; break;
		case '/': i=3; break;
		case '(': i=4; break;
		case ')': i=5; break;
		case '#': i=6; break;
	}
	switch (just_scanned_operator) {
		case '+':j = 0;break;
		case '-':j = 1;break;
		case '*':j = 2;break;
		case '/':j = 3;break;
		case '(':j = 4;break;
		case ')':j = 5;break;
		case '#':j = 6;break;
	}
	switch (youxianji[i][j]) {
	case '>':
		return 1;
	case '<':
		return -1;
	case '=':
		return 0;
	}
}

// 用于简单计算+，-，*，/，operator表示操作符，left_operand表示左操作数，right_operand表示右操作数，结果通过result返回。函数返回值表示计算状态：0，计算成功；1，不成功。
int caculate(char operator, char left_operand, char right_operand, int * result) {
	int i , j;
	switch (left_operand) {
		case'0': i = 0;break;
		case'1': i = 1;break;
		case'2': i = 2;break;
		case'3': i = 3;break;
		case'4': i = 4;break;
		case'5': i = 5;break;
		case'6': i = 6;break;
		case'7': i = 7;break;
		case'8': i = 8;break;
		case'9': i = 9;break;
	}
	switch (right_operand) {
		case'0': j = 0;break;
		case'1': j = 1;break;
		case'2': j = 2;break;
		case'3': j = 3;break;
		case'4': j = 4;break;
		case'5': j = 5;break;
		case'6': j = 6;break;
		case'7': j = 7;break;
		case'8': j = 8;break;
		case'9': j = 9;break;
	}
	
	switch (operator) {
		case '+':*result = i + j;break;
		case '-':*result = i - j;break;
		case '*':*result = i * j;break;
	case '/':
		if (j!=0) {
			*result = i / j;
		}
		else{
			printf("除数不能为零！\n");
			exit(0);
		}
		break;
	}
	return 0;
}

// 最主要的函数，用于计算表达式的值，比如#1+2#。返回值表示求值状态：0，合法表达式，成功求值；1，表达式不合法。result变量用于返回计算结果。
int evaluate(char * expression, int * result) {
	Stack OPTR;
	Stack OPND;
	char left_operand;
	char right_operand;
	init_stack(&OPTR);
	init_stack(&OPND);
	
	int char_position = 0;
	push(OPTR, expression[char_position]);
	char_position +=1;
	char top;
	char w = expression[char_position];
	
	while(w != '#' || top != '#')
	{
		if(is_operand(w))
		{
			push(OPND, w);
			char_position += 1;
			w = expression[char_position];
		}
		if(is_operator(w))
		{   char c;
			get_top(OPTR, &c);
			char Total;
			int RESULT;
			switch (compare_operators(c,w)) {
			case -1:
				push(OPTR, w);
				w = expression[++char_position];
				break;
			case 0:
				pop(OPTR, &c);
				w = expression[++char_position];
				break;
			case 1:
				pop(OPND, &right_operand);
				pop(OPND, &left_operand);
				pop(OPTR, &c);
				if (c == '#' || left_operand == 0){
					*result = 1;
					return *result;
				}else {
					caculate(c, left_operand, right_operand, &RESULT);
					Total = RESULT + 48;
					push(OPND, Total);
				}
				break;
			}
		}
		get_top(OPTR, &top);
	}
	get_top(OPND, &top);
	*result = top - 48;
	return *result;
}

int main(int argc, char * argv[]) {
	int result;
	int is_exp_valid = evaluate("#1+(1+1)*3/2-2#", &result);
	printf("result:%d",is_exp_valid);
}
